home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QRZ! Ham Radio 3
/
QRZ Ham Radio Callsign Database - Volume 3.iso
/
world
/
amiga
/
7pl204am.lzh
/
7PLUS204
/
SOURCE
/
ENCODE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-07-17
|
17KB
|
633 lines
#include "7plus.h"
#include "globals.h"
/*
*** encode a file. split, if desired/needed. create correction file.
***
***
*/
int encode_file (char *name, long blocksize, char *searchbin,
int _part, char *head_foot)
{
int part, parts, blocklines, curline;
int correct, corrlines , corrpart, corrline, tune;
uint csequence;
ulong ftimestamp, ftstamp0 , after[16], *af, h;
long binbytes, binb0, position, size, corrsize;
char destname[13], hdrname[MAXFNAME], filename[13], corrname[13];
char orgname[66], inpath[MAXFPATH], line[81], line2[81];
char dummi[20], dummi2[20], *q, *r;
char go_buf[257], stop_buf[257], cor_head[129];
FILE *in, *out, *corr;
register i, j, k;
correct = i = corrpart = corrlines = blocklines = 0;
*destname = *hdrname = *filename = *corrname = *inpath = *orgname = EOS;
*_file = *go_buf = *stop_buf = EOS;
in = out = corr = NULLFP;
ftimestamp = ftstamp0 = 0UL;
corrsize = 0L;
#ifdef TWO_CHAR_SEP
tune = 1;
#else
tune = 0;
#endif
if (fls)
if (!test_exist ("7plus.fls"))
unlink ("7plus.fls");
if (searchbin)
{
/* Get serchpath for binary (original) file. */
fnsplit (searchbin, _drive, _dir, _file, _ext);
sprintf (inpath, "%s%s", _drive, _dir);
}
q = name;
/* create correction file, if ext of input file is .ERR */
if ((r = strrchr (q, '.')) != NULL)
if (!strnicmp (".err", r, 4))
{
/* OK, input file is an error file */
correct = 1;
if ((i = crc_file (q, "7PLUS error", "00\n", 1)) != 0)
if (i != 17)
return (i);
corr = fopen (q, OPEN_READ_TEXT);
/* Find starting line. */
while ((r = my_fgets (line, 80, corr)) != NULL)
if (!strncmp (line, "7PLUS ", 6))
break;
if (!r)
{
printf ("\007'%s': invalid error report. Break.\n", q);
fclose (corr);
return (7);
}
/* Get name, lines per part, and length of original
file from error file.*/
*orgname = EOS;
binb0 = 0L;
ftstamp0 = 0UL;
sscanf (line+20, "%12s %s /%66[^/]/ %ld",
corrname, dummi, orgname, &binb0);
corrlines = get_hex (dummi);
if (!*orgname)
{
binb0 = 0L;
sscanf (line+20, "%s %s %ld",
dummi, dummi, &binb0);
}
strlwr (corrname);
if (extended != '*' || !*orgname)
strcpy (orgname, corrname);
/* Build complete filename for original file */
if (!*_file)
strcat (inpath, orgname);
else
{
strcat (inpath, _file);
strcat (inpath, _ext);
}
q = inpath;
}
if (!(in = fopen (q, OPEN_READ_BINARY)))
{
printf ("\007'%s' not found. Break.\n", q);
return (2);
}
if (head_foot && !correct)
read_tb (head_foot, go_buf, stop_buf);
/* Get file's timestamp */
#if defined (__MSDOS__) || (__TOS__)
ftimestamp = get_filetime (in);
#else
ftimestamp = get_filetime (q);
#endif
/* determine size of original file. This could be done with filestat(),
but it's not available on all compilers. */
fseek (in, 0L, SEEK_END); /* position read pointer to end of file. */
size = ftell (in); /* get size. */
fseek (in, 0L, SEEK_SET); /* reposition to beginning of file. */
if (correct && binb0 && size != binb0)
{
printf (notsame, "error report");
fclose (in);
fclose (corr);
return (15);
}
part = parts = 1;
if (!correct)
{
/* Bufferize input, if we're encoding. */
setvbuf (in, NULL, _IOFBF, buflen);
/* if blocksize is greater then try to split into blocksize-50000 parts */
if (blocksize > 50000L)
{
blocksize -= 50000L;
/* calculate how many ascii-bytes per part are needed to get roughly
equal filelengths. */
blocksize = (((size + 61) / 62) + (blocksize - 1)) / blocksize;
blocksize *= 62;
}
/* if blocksize is defined as zero or if it's bigger than the file,
set it to filelength */
if (!blocksize || blocksize > size)
blocksize = size;
/* automatically split into 512 line parts, if file is bigger. */
if (blocksize > (512 * 62))
{
blocksize = 512 * 62;
printf ("Blocksize limited to 512 lines per file.\n");
}
/* how many lines do the parts contain? */
blocklines = (int) ((blocksize + 61) / 62);
/* how many parts result from that? */
parts = (int) ((size + blocksize-1) / blocksize);
if (parts > 255)
{
printf ("\007Not more than 255 parts allowed.\n");
printf ("Choose different blocksize. Break.\n");
fclose (in);
return (8);
}
}
else
if (blocksize > 50000L || blocksize == 138L*62L)
blocksize = 9940L;
else
blocksize = (blocksize/62) *71;
/* generate filenames */
fnsplit (q, NULL, NULL, _file, _ext);
sprintf (orgname, "%s%s", _file, _ext);
build_DOS_name (_file);
build_DOS_name (_ext);
/* make sure, the name isn't longer than 8 chars
and extension not longer 4 (including dot). */
_file[8] = _ext[3] = EOS;
strcpy (destname, _file);
sprintf (hdrname, "%s%s%s", _file, _ext[0]?".":"", _ext);
strupr (hdrname);
if (!correct)
printf ("\n-----------\nEncoding...\n-----------\n\n");
else
printf ("\n---------------------------\nCreating correction file...\n\
---------------------------\n\n");
if (!_part)
part = 1;
else
{
if (_part > parts || _part < 0)
{
printf ("\007Can't encode part %d of %d... You're pulling my leg!\n", _part, parts);
return (1);
}
part = _part;
}
/* encode parts */
for (; part<parts+1 ; part++)
{
if (!correct)
{
/* generate output filename. *.7PL, if unsplit. *.PXX if split.
XX represents a two digit hex number. */
if (parts == 1)
{
sprintf (filename, "%s%s", destname, ".7pl");
printf ("'%s': Writing.\r", filename);
}
else
{
sprintf (filename, "%s.p%02x", destname, part);
printf ("'%s': Writing part %03d of %03d.\r", filename, part, parts);
}
fflush (stdout);
/* check, if output file already exists. */
test_file (out, filename, 0, 12);
}
else /* we're creating a correction file, set name accordingly. */
{
fnsplit (corrname, NULL, NULL, destname, NULL);
sprintf (filename, "%s.cor", destname);
}
out = fopen (filename, OPEN_WRITE_TEXT);
setvbuf (out, NULL, _IOFBF, buflen);
if (!correct)
{
if (part == parts && parts > 1)
{
if (size % blocksize)
blocksize = size % blocksize;
blocksize = ((blocksize + 61 ) / 62) *62;
}
top_bottom (out, go_buf, hdrname, part, parts);
/* output header */
sprintf (line, " go_7+. %03d of %03d %-12s %07ld %04X %03X (7PLUS v2.0) \
\xb0\xb1\xb2%c", part, parts, hdrname, size,
(uint)(((blocksize+61)/62) * 64), blocklines, extended);
mcrc (line, 1);
add_crc2 (line);
fprintf (out, "%s%s", line, delimit);
if (part == 1 && extended == '*')
{
sprintf (line, "///////////////////////////////////////////////////\
///////////\xb0\xb1\xb2*");
memcpy (line+1, orgname, strlen(orgname));
mcrc (line, 1);
add_crc2 (line);
fprintf (out, "%s%s", line, delimit);
}
}
else
{
/* output correction file header */
strcpy (dummi2, filename);
strupr (dummi2);
strupr (corrname);
sprintf (cor_head, " go_text. %s%s7PLUS correction: %s %ld %03X", dummi2, delimit, corrname, size, corrlines );
if (ftimestamp)
{
sprintf (dummi, " [%lX]", ftimestamp);
strcat (cor_head, dummi);
}
strcat (cor_head, delimit);
corrsize += fprintf (out, "%s", cor_head) +tune;
strlwr (corrname);
fscanf (corr, "%s", dummi2);
corrpart = get_hex (dummi2);
corrsize += fprintf (out, " P%02x:%s", corrpart, delimit) +tune;
printf ("Compiling: '%s'\r", filename);
fflush (stdout);
}
curline = j = 0;
binbytes = 0L;
if (_part)
fseek (in, (long) blocksize * (_part -1), SEEK_SET);
/* get bytes from original file until it ends or blocksize is reached. */
while (!feof(in) && ((binbytes < blocksize) || parts == 1) || correct)
{
csequence = 0;
if (correct)
{
/* get number of part and number of line to put into correction file
from error file */
fscanf (corr, "%s", dummi2);
corrline = get_hex (dummi2);
if (corrline == 0xfff || corrsize > blocksize)
{
if (corrline == 0xfff)
{
corrpart = 0;
fscanf (corr, "%s", dummi2);
corrpart = get_hex (dummi2);
if (!corrpart)
{
sscanf (dummi2, "[%lX]", &ftstamp0);
corrsize = (long) blocksize+1;
printf ("\n");
}
else
{
fscanf (corr, "%s", dummi2);
corrline = get_hex (dummi2);
}
}
if (corrsize > blocksize)
{
corrsize = 0L;
/* if we were creating a correction file, complete it. */
fprintf (out, " P00:%s________%s stop_text.%s",
delimit, delimit, delimit);
if (endstr)
fprintf (out, "%s%s", endstr, delimit);
fclose (out);
crc_file (filename, "7P", " P00:\n", 0);
if (!corrpart)
break;
fnsplit (corrname, NULL, NULL, destname, NULL);
sprintf (filename, "%s.c%02x", destname, part++);
out = fopen (filename, OPEN_WRITE_TEXT);
setvbuf (out, NULL, _IOFBF, buflen);
corrsize += fprintf (out, "%s", cor_head) +tune;
printf ("Compiling: '%s'\r", filename);
fflush (stdout);
}
corrsize += fprintf (out, " P%02X:%s", corrpart, delimit) +tune;
}
curline = corrline ;
/* calculate position in original file to get data from. */
position = (long)(corrpart-1) * 62 * (long)corrlines +
62 * (long)corrline ;
/* position read pointer. */
fseek (in, position, SEEK_SET);
corrsize += fprintf (out, " L%03X:%s", corrline , delimit) +tune;
}
/* get two groups of 31 bytes and stuff them into 2 * 8 longs. */
af = after;
for (i=0; i<2; i++, af+=8)
{
/* Get 31 Bytes and put them into 8 longs. */
for(j=0; j<8; j++)
{
af[j] = 0L;
for (k=(j==7)?2:3; k>-1; k--)
{
if ((h = fgetc (in)) == EOF)
{
if (!i && !j && k == 3)
i = 255;
h = 0L;
}
af[j] = (af[j] << 8) | h;
}
}
/* Rearrange into 8 31bit values. */
af[7] = af[7] | ((af[6] & 127L) << 24);
af[6] = (af[6] >> 7) | ((af[5] & 63L ) << 25);
af[5] = (af[5] >> 6) | ((af[4] & 31L ) << 26);
af[4] = (af[4] >> 5) | ((af[3] & 15L ) << 27);
af[3] = (af[3] >> 4) | ((af[2] & 7L ) << 28);
af[2] = (af[2] >> 3) | ((af[1] & 3L ) << 29);
af[1] = (af[1] >> 2) | ((af[0] & 1L ) << 30);
af[0] = (af[0] >> 1);
}
/* i is 256, then no bytes were read. End of file. */
if (i == 256)
break;
binbytes += 62;
/* write code line to output file. do radix216 conversion, crc
calculation and ascii conversion as we go along. */
for (i=j=0;i<16;i++)
{
line2[j++] = code[(int)(after[i] % 0xd8L)];
after[i] /= 0xd8L;
line2[j++] = code[(int)(after[i] % 0xd8L)];
after[i] /= 0xd8L;
line2[j++] = code[(int)(after[i] % 0xd8L)];
line2[j++] = code[(int)(after[i] / 0xd8L)];
}
for (i=0;i<64;i++)
csequence = crctab[csequence>>8] ^ (((csequence&255)<<8) |
(byte) line2[i]);
/* package line number and crc into three radix216 bytes and add
to code line. */
after[0] = ((long)(curline & 0x1ff) << 14) | (csequence & 0x3fff);
line2[j++] = code[(int) (after[0] % 0xd8L)];
after[0] /= 0xd8L;
line2[j++] = code[(int) (after[0] % 0xd8L)];
line2[j++] = code[(int) (after[0] / 0xd8L)];
add_crc2 (line2);
corrsize += fprintf (out, "%s", line2) +tune;
/* conclude line with line separator. */
corrsize += fprintf (out, delimit);
curline++; /* increase line counter. */
}
if (!correct) /* put end indicator into output file. */
{
strupr (filename);
/* Add timestamp */
sprintf (line, " \
\xb0\xb1\xb2\xdb");
if (parts > 1)
sprintf (line2, " stop_7+. (%s/%02X) [%lX]", filename, parts, ftimestamp);
else
sprintf (line2, " stop_7+. (%s) [%lX]", filename, ftimestamp);
memcpy (line, line2, strlen(line2));
mcrc (line, 1);
add_crc2 (line);
fprintf (out, "%s%s", line, delimit);
top_bottom (out, stop_buf, hdrname, part, parts);
if (endstr)
fprintf (out, "%s%s", endstr, delimit);
/* OK. This part is done. */
fclose (out);
}
else
if (ftstamp0 && ftstamp0 != ftimestamp)
printf ("\007Warning: Timestamp in error report differs from the original file!\n");
if (ferror(out)) /* did any errors occur while writing? */
{
printf ("\n\007Write error. Break.\n");
fclose (in);
return (1);
}
if (_part || correct)
part = 256;
} /* end of for() */
/* all parts done.
tell user about action. */
if (!correct)
{
printf ("\n\nEncoding successful!\n");
if (fls)
{
if (!(out = fopen ("7plus.fls", OPEN_WRITE_TEXT)))
return (14);
fnsplit (filename, NULL, NULL, _file, NULL);
fprintf (out, "%d %s\n", parts, _file);
fclose (out);
}
}
fclose (in);
return (0);
}
/*
*** Get info from header ifile
***
***
*/
int read_tb (char *name, char *go_top, char *go_bottom)
{
FILE *rfile;
int i, j, prev;
char *p, *q, line [81], compare[10];
i = j = prev = 0;
q = NULL;
if (!(rfile = fopen (name, OPEN_READ_TEXT)))
{
printf (cant, name);
return (2);
}
q = go_top;
strcpy (compare, "@@TOP\n");
while (1 == 1)
{
p = my_fgets (line, 80, rfile);
if (strnicmp (p, compare, strlen(compare)))
{
*q = EOS;
j = EOF;
}
else
{
i = 0;
do
{
prev = j;
q[i] = j = fgetc(rfile);
if (j == '\r')
continue;
i++;
}
while (j != EOF && !(j == '@' && prev == '\n') && i < 256);
q[i-2] = '\n';
q[i-1] = EOS;
}
if (j != '@' && j != EOF)
do
{
prev = j;
j = fgetc(rfile);
}
while (j != EOF && !(j == '@' && prev == '\n'));
if (j == '@')
ungetc (j, rfile);
if (j == EOF && q == go_bottom)
break;
if (q == go_top)
{
q = go_bottom;
strcpy (compare, "@@BOTTOM\n");
}
}
fclose (rfile);
return (0);
}
/*
*** output head or foot
***
***
*/
int top_bottom (FILE *wfile, char *top_bot, char *orgname, int part, int parts)
{
int i;
char __file[9], __ext[5];
fnsplit (orgname, NULL, NULL, _file, _ext);
strcpy (__file, _file);
strcpy (__ext , _ext );
strlwr (_file);
strlwr (_ext );
i = 0;
while (top_bot[i] != EOS)
{
if (top_bot[i] == '%')
{
i++;
if (!top_bot[i])
break;
switch (top_bot[i])
{
case 'o': fprintf (wfile, "%s%s", _file, _ext);
break;
case 'O': fprintf (wfile, "%s%s", __file, __ext);
break;
case 'n': fprintf (wfile, "%s.p%02x", _file, part);
break;
case 'N': fprintf (wfile, "%s.P%02X", __file, part);
break;
case 'p': fprintf (wfile, "%d", part);
break;
case 'P': fprintf (wfile, "%02X", part);
break;
case 'q': fprintf (wfile, "%d", parts);
break;
case 'Q': fprintf (wfile, "%02X", parts);
break;
case '%': fprintf (wfile, "%s", "%");
break;
default : fprintf (wfile, "%%%c", top_bot[i]);
}
i++;
}
if (!top_bot[i])
break;
if (top_bot[i] == '\n')
fprintf (wfile, "%s", delimit);
else
my_putc (top_bot[i], wfile);
i++;
}
return (0);
}